import chokidar from 'chokidar';
import ftp from 'basic-ftp';
import { readFile } from 'fs/promises';

let ftpConfig;
let directories;

// 加载配置文件
async function loadConfig() {
    try {
        const configData = await readFile('./config.json', 'utf8');
        const config = JSON.parse(configData);
        ftpConfig = config.ftpConfig;
        directories = config.directories;
    } catch (err) {
        console.error('读取配置文件时出错:', err);
        process.exit(1);
    }
}

// 创建 FTP 客户端实例
const client = new ftp.Client();
let taskQueue = [];
let isProcessing = false;

/**
 * 获取本地目录对应的正则表达式
 * @param {string} remoteDirectory - 服务器目录
 * @returns {RegExp} 本地目录对应的正则表达式
 */
function getLocalDirRegex(remoteDirectory) {
    const localDir = directories.find(dir => dir.remote === remoteDirectory)?.local;
    if (!localDir) {
        throw new Error(`未找到与远程目录 ${remoteDirectory} 对应的本地目录`);
    }
    return new RegExp(`^${localDir.replace(/[\\/]/g, '\\\\')}`, 'i');
}

// 连接到 FTP 服务器，添加重试机制
async function connectToFTP(maxRetries = 3, retryDelay = 2000) {
    let retries = 0;
    while (retries < maxRetries) {
        try {
            await client.access(ftpConfig);
            console.log('已成功连接到 FTP 服务器');
            return;
        } catch (err) {
            retries++;
            if (retries < maxRetries) {
                console.error(`连接失败，尝试第 ${retries} 次重试...`, err);
                await new Promise(resolve => setTimeout(resolve, retryDelay));
            } else {
                console.error('连接到 FTP 服务器失败，已达到最大重试次数:', err);
            }
        }
    }
}

// 处理任务队列
async function processQueue() {
    if (isProcessing || taskQueue.length === 0) return;
    isProcessing = true;
    const task = taskQueue.shift();
    try {
        await task();
    } catch (err) {
        console.error('处理任务时出错:', err);
    }
    isProcessing = false;
    processQueue();
}

// 创建服务器上的文件夹
async function createDirectory(dirPath, remoteDirectory) {
    return new Promise((resolve, reject) => {
        taskQueue.push(async () => {
            try {
                const localDirRegex = getLocalDirRegex(remoteDirectory);
                const relativePath = dirPath.replace(localDirRegex, '');
                const remoteDirPath = `${remoteDirectory}${relativePath.replace(/[\\/]/g, '/')}`;
                await client.ensureDir(remoteDirPath);
                console.log(`文件夹 ${remoteDirPath} 已在服务器创建`);
                resolve();
            } catch (err) {
                console.error(`创建文件夹时出错:`, err);
                reject(err);
            }
        });
        processQueue();
    });
}

// 上传文件到 FTP 服务器
async function uploadFile(filePath, remoteDirectory) {
    console.log("filePath=>", filePath);
    return new Promise((resolve, reject) => {
        taskQueue.push(async () => {
            try {
                const localDirRegex = getLocalDirRegex(remoteDirectory);
                const relativePath = filePath.replace(localDirRegex, '');
                console.log("localDirectory=>", directories.find(dir => dir.remote === remoteDirectory).local);
                console.log("r1=>", relativePath);
                const remoteFilePath = `${remoteDirectory}${relativePath.replace(/[\\/]/g, '/')}`;
                console.log(relativePath, "=>", remoteFilePath);
                await client.uploadFrom(filePath, remoteFilePath);
                console.log(`文件 ${filePath} 已成功上传到 ${remoteFilePath}`);
                resolve();
            } catch (err) {
                console.error(`上传文件 ${filePath} 时出错:`, err);
                reject(err);
            }
        });
        processQueue();
    });
}

// 删除服务器上的文件
async function deleteFile(filePath, remoteDirectory) {
    return new Promise((resolve, reject) => {
        taskQueue.push(async () => {
            try {
                const localDirRegex = getLocalDirRegex(remoteDirectory);
                const relativePath = filePath.replace(localDirRegex, '');
                const remoteFilePath = `${remoteDirectory}${relativePath.replace(/[\\/]/g, '/')}`;
                await client.remove(remoteFilePath);
                console.log(`文件 ${remoteFilePath} 已从服务器删除`);
                resolve();
            } catch (err) {
                console.error(`删除文件 ${remoteFilePath} 时出错:`, err);
                reject(err);
            }
        });
        processQueue();
    });
}

// 监听文件变化
async function watchFiles() {
    await loadConfig();
    await connectToFTP();

    directories.forEach(({ local, remote, ignored }) => {
        console.log("local=>", local);
        console.log("remote=>", remote);
        console.log("ignored=>", ignored);
        const watcher = chokidar.watch(local, {
            ignored: ignored, // 忽略隐藏文件
            persistent: true
        });

        watcher.on('change', async (filePath) => {
            console.log(`文件 ${filePath} 已修改，开始上传...`);
            await uploadFile(filePath, remote);
        });

        watcher.on('unlink', async (filePath) => {
            await deleteFile(filePath, remote);
        });

        watcher.on('add', async (filePath) => {
            console.log(`新文件 ${filePath} 已添加，开始上传...`);
            await uploadFile(filePath, remote);
        });

        watcher.on('addDir', async (dirPath) => {
            console.log(`新文件夹 ${dirPath} 已创建，开始在服务器创建对应文件夹...`);
            await createDirectory(dirPath, remote);
        });
    });

    process.on('SIGINT', async () => {
        console.log('正在关闭 FTP 连接...');
        await client.close();
        process.exit();
    });
}

watchFiles();